import requests
import json
import base64
import random
import time
import re
from Crypto.Cipher import AES
from lxml import etree   

cloudMusic = {}
# cookie = login_in.cookies
headers = {
    'authority': 'music.163.com',
    'sec-ch-ua': '^\\^',
    'sec-ch-ua-mobile': '?0',
    'upgrade-insecure-requests': '1',
    'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.93 Safari/537.36',
    'accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9',
    'sec-fetch-site': 'same-origin',
    'sec-fetch-mode': 'navigate',
    'sec-fetch-dest': 'iframe',
    'referer': 'https://music.163.com/',
    'accept-language': 'zh-CN,zh;q=0.9',
    'cookie': 'MUSIC_EMAIL_U=4ec00d0263276c70b71593cf95bc61008ba689fefc8b4f0810f90ab860ade29ac1f412922aaeb58126f03d53a23f3c63c3061cd18d77b7a0; _iuqxldmzr_=32; _ntes_nuid=d55c1aad64f1fe19f6c776a4842992df; _ntes_nnid=d55c1aad64f1fe19f6c776a4842992df,1618886346498; playliststatus=visible; NMTID=00Oi0mGPvWmNzsMnEt0iaTsD_qun14AAAF47SVU5A; WEVNSM=1.0.0; WNMCID=wllinz.1618886348390.01.0; WM_TID=KXIbApzjnDhEQBEARRdrhK33SWItABSB; NTES_YD_SESS=NRIO3h4EZ05.RLgdNkaFDkLgt2jkpM7FeClQ4fViOOZR0UVp0AITEqEmBfJZVihqwsIzkIm262CEvEhEI.xHYADedYPZQu9.PSIkoLspo7VlMjzsJnN5eWzry1xqBWgQyHgkBqZ2l_8_qW4fjfPdYWHmI18nfBqeXJ2u0ZWamCMykT6dFLqvt8tzOv_xVHEwOl4FU03HRbbqRguD11RLY_wETz51OZmE6QqLQWwMgdeuF; S_INFO=1618926254^|0^|3&80^#^#^|18571826829; P_INFO=18571826829^|1618926254^|1^|study^|00&99^|null&null&null^#US&null^#10^#0^#0^|&0^|null^|18571826829; OUTFOX_SEARCH_USER_ID_NCOO=1052844159.6756152; UM_distinctid=178f3c6f5ba936-083adbb9e12cc4-3f356b-144000-178f3c6f5bb8fa; hb_MA-BFF5-63705950A31C_source=ke.study.163.com; _antanalysis_s_id=1619004186597; playerid=46407284; ntes_kaola_ad=1; WM_NI=STAsyDxeqqOURrrdOwagwCY0mzLh^%^2BpxWaVQZg1E2dQfHqM5PFp6oPKL5xUeZz9XKgT5jyLj7lVPNIFywuAo^%^2BP9X7pocEHonRsEzlj1eC9^%^2Fa7BsjOYMIHVN^%^2Bdt3obezZPOXQ^%^3D; WM_NIKE=9ca17ae2e6ffcda170e2e6eed9bb64f2aea793ed7ebce78aa6c45a939b8babaa74f4ad9d8deb41fbb1e1a2d82af0fea7c3b92a918c8f94fc50bcbbbf92ce5f92aebe85ce7da3b9b9a4dc3cafa68489aa7cbc89afb7d452a5ef8bd3e75ba698bfaeb85c86b0fa90d34190ebb8b6e852bae798ace660f7b6b7ade93db08aa0afcc4ebba9bba2ee2194e798d8f365a19b8890ed5ab19bb68de93ba79df7d0e43d82ada6b0dc478b989aafaa70b8eda183e8729a9081b9d437e2a3; MUSIC_U=ab509875e76f4a371c02e25068c9597005947b73657916bb99a50007177d9b8f9cb4377b2d7ba249; __remember_me=true; __csrf=d59d0637131f54976adc993f9460f030; JSESSIONID-WYYY=uCZFxdJ3FyOQvgdS424wv3uet7lFNdSS^%^2FwqtQCUMenofJF5^%^5CCQpCwIfOV4MrUImiBwa^%^2BmOZ3Zf bB4jet^%^2B9i2XXHArpnOkr8W1V6DANDfekly^%^2BFS4DTlKF^%^2Fzw08gH8oM^%^2FNQ8rrp^%^2FCsVQefox2MfPFYNYHstStrBiFb2V7kxxRQ42A8HKP^%^3A1620043080203'
}

res = requests.get('https://music.163.com/discover/playlist/?cat=%E7%B2%A4%E8%AF%AD', headers=headers)      # 一页有35个歌单

resxml = etree.HTML(res.text) # 解析源码
elems = resxml.xpath('//*[@id="m-pl-container"]/li[*]/p[1]/a/@href')
base_url = 'https://music.163.com'
listlinks = [base_url + elem for elem in elems]

for listlink in listlinks:
    r = requests.get(listlink,headers=headers)
    rxml = etree.HTML(r.text)
    songs = rxml.xpath('//ul[@class="f-hide"]/li/a/@href')  
    for song in songs:
        songid = ''.join(re.findall(r"\d+\.?\d*",song))     # 字符串,而不是列表

        with open(r'Learning Record\Learning pro\songid log.txt','r',encoding='utf-8') as f_log:
            ID = f_log.read()     #FileNotFoundError

        if songid not in ID:    # 判断日志里是否有内容,没有就开始爬虫
            with open(r'Learning Record\Learning pro\songid log.txt','a',encoding='utf-8') as f_log:    # 断点日志
                f_log.write(str(songid))
                f_log.write('\n')
            
            # 爬取歌名和歌手
            urlsong = 'https://music.163.com'+song
            r_song = requests.get(urlsong,headers=headers)
            rxml_song = etree.HTML(r_song.text)
            cloudMusic['songName'] = rxml_song.xpath('//em[@class="f-ff2"]/text()')
            cloudMusic['singer'] = rxml_song.xpath('//p[@class="des s-fc4"]/span/@title')

            # 爬取热评
            param2 = "010001"   
            param3 = "00e0b509f6259df8642dbc35662901477df22677ec152b5ff68ace615bb7b725152b3ab17a876aea8a5aa76d2e417629ec4ee341f56135fccf695280104e0312ecbda92557c93870114af6c9d05c4f7f0c3685b7a46bee255932575cce10b424d813cfe4875d3e82047b97ddef52741d546b8e289dc6935b3ece0462db0a22b8e7"
            param4 = "0CoJUm6Qyw8W8jud"

            def AES_encrypt(text, key, iv):
                pad = 16 - len(text) % 16
                text = text + pad * chr(pad)
                text = text.encode("utf-8")
                encryptor = AES.new(key.encode('utf-8'), AES.MODE_CBC, iv)
                encrypt_text = encryptor.encrypt(text)
                encrypt_text = base64.b64encode(encrypt_text)
                return encrypt_text.decode('utf-8')

            def asrsea(p1, p2, p3, p4):
                res = {}
                rand_num = "aq9d7cvBOJ1tzj1o"
                vi = b"0102030405060708"
                h_encText = AES_encrypt(p1, p4, vi)
                h_encText = AES_encrypt(h_encText, rand_num, vi)
                res["encText"] = h_encText
                res["encSecKey"] = "5dec9ded1d7223302cc7db8d7e0428b04139743ab7e3d451ae47837f34e66f9a86f63e45ef20d147c33d88530a6c3c9d9d88e38586b42ee30ce43fbf3283a2b10e3118b76e11d6561d80e33ae38deb96832b1a358665c0579b1576b21f995829d45fc43612eede2ac243c6ebb6c2d16127742f3ac913d3ac7d6026b44cee424e"
                return res

            cloudMusic['Comment'] = []
            # for i in range(11):
            i = 0
            curr_time = int(time.time() * 1000)
            param1 = json.dumps(
                {
                    "csrf_token": "",
                    "cursor": "%s" % curr_time,
                    "offset": str(i*20), 
                    "orderType": "2", 
                    "pageNo": str(i+1),
                    "pageSize": "20", 
                    "rid": "R_SO_4_%s" % songid, 
                    "threadId": "R_SO_4_%s" % songid
                }
                                )

            asrsea_res = asrsea(param1, param2, param3, param4)

            url = "https://music.163.com/weapi/comment/resource/comments/get?csrf_token="

            param_data = {"params": asrsea_res["encText"],
                        "encSecKey": asrsea_res["encSecKey"]}
            rct = requests.post(url, headers=headers, data=param_data, verify=False)
            print(rct.text)
            try:
                # if rct.json()['data']['hotComments'] is not 'null':
                hotComments = rct.json()['data']['hotComments']
                for hotComment in hotComments:
                    cloudMusic['Comment'].append(hotComment['content'])
                data = json.dumps(cloudMusic,ensure_ascii=False).encode('utf-8').decode('utf-8') 
                with open(r'Learning Record\Learning pro\cloudMusic.json','a',encoding='utf-8') as file_obj:
                    file_obj.write(data)
                    file_obj.write('\n')
                # else :
                #     continue
            except(KeyError,TypeError):
                print('评论为空或IP被封')
                
# # 参数与歌ID无关,且没有规则,如何解决? >> selenium抓取html[似乎有反爬机制]  >> 确认其加密后百度搜索
# rct = requests.post('https://music.163.com/weapi/comment/resource/comments/get', headers=headers, params=params, data=data) 
# hotComments = rct.json()['data']['hotComments']
# for hotComment in hotComments:
#     print(hotComment['content'])